
package com.sun.showcase.biz.mall.service.impl;

import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.sun.showcase.biz.mall.dao.PayOrderDao;
import com.sun.showcase.biz.mall.service.*;
import com.sun.showcase.client.domain.mall.*;
import com.sun.showcase.client.query.mall.*;
import com.sun.showcase.client.vo.order.PayOrderMiniAppEntity;
import com.sun.showcase.pojo.DataGrid;
import com.sun.showcase.pojo.Pager;
import com.sun.showcase.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service("payOrderService")
@Transactional
public class PayOrderServiceImpl implements PayOrderService{
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	@Autowired
	private PayOrderDao payOrderDao;
	@Autowired
	private WxPayService wxPayService;
	@Autowired
	private OrderService orderService;
	@Autowired
	private OrderGoodsService orderGoodsService;
	@Autowired
	private DistributionService distributionService;
	@Autowired
	private MemberService memberService;
	@Autowired
	private MemberLevelService memberLevelService;
	@Autowired
	private MemberBillService memberBillService;
	@Autowired
	private PlatformConfigService platformConfigService;
	
	public void setPayOrderDao(PayOrderDao dao) {
		this.payOrderDao = dao;
	}

	public DataGrid datagrid(PayOrderQuery payOrderQuery) {
		DataGrid j = new DataGrid();
		Pager<PayOrder> pager  = find(payOrderQuery);
		j.setRows(getQuerysFromEntitys(pager.getRecords()));
		j.setTotal(pager.getTotalRecords());
		return j;
	}

	private List<PayOrderQuery> getQuerysFromEntitys(List<PayOrder> payOrders) {
		List<PayOrderQuery> payOrderQuerys = new ArrayList<PayOrderQuery>();
		if (payOrders != null && payOrders.size() > 0) {
			for (PayOrder tb : payOrders) {
				PayOrderQuery b = new PayOrderQuery();
				BeanUtils.copyProperties(tb, b);
				payOrderQuerys.add(b);
			}
		}
		return payOrderQuerys;
	}

	private Pager<PayOrder> find(PayOrderQuery payOrderQuery) {
		Page<PayOrder> page = PageHelper.startPage(payOrderQuery.getPage().intValue(), payOrderQuery.getRows().intValue());
		List<PayOrder> list = payOrderDao.findList(payOrderQuery);
		Pager<PayOrder> pager = new Pager<PayOrder>();
		pager.setRecords(list);
		pager.setTotalRecords(page.getTotal());
		return  pager;
		
	}
	


	public PayOrder add(PayOrderQuery payOrderQuery) {
		PayOrder t = new PayOrder();
		BeanUtils.copyProperties(payOrderQuery, t);
		t.setCreateTime(new Date());
	    t.setId(UuidUtil.get32UUID());
		payOrderDao.save(t);
		payOrderQuery.setId(t.getId());
		return t;
		
	}

	public void update(PayOrderQuery payOrderQuery) {
		PayOrder t = payOrderDao.getById(payOrderQuery.getId());
	    if(t != null) {
	    	BeanUtils.copyProperties(payOrderQuery, t);
	    	payOrderDao.update(t);
		}
	}
	
	/**
	 * 根据条件更新部分字段   新建一个query封装需要更新的字段
	 * searchMap封装更新条件
	 * */
	public void updatePart(PayOrderQuery payOrderQuery) {
	    payOrderDao.updatePart(payOrderQuery);
	}

	public void delete(String[] ids) {
		payOrderDao.deleteAc(ids);
	}

	//逻辑删除 更新状态位
	public void deletePt(String[] ids) {
		payOrderDao.deletePt(ids);
	}

	public PayOrder get(PayOrderQuery payOrderQuery) {
		return payOrderDao.getById(payOrderQuery.getId());
	}

	public PayOrder get(String id) {
		return payOrderDao.getById(id);
	}

	
	public List<PayOrderQuery> listAll(PayOrderQuery payOrderQuery) {
	    List<PayOrder> list = payOrderDao.findList(payOrderQuery);
		List<PayOrderQuery> listQuery =getQuerysFromEntitys(list) ;
		return listQuery;
	}

	@Override
	public ExecuteResult<WxPayMpOrderResult> miniAppPay(PayOrderMiniAppEntity entity) {
		ValidatorUtils.validate(entity);
		ExecuteResult<WxPayMpOrderResult> res = new ExecuteResult<WxPayMpOrderResult>();
		if(entity.getOrderIds() == null || entity.getOrderIds().size()==0) {
			res.addErrorMessage("无效参数");
			return res;
		}
		List<Order> orderList = new ArrayList<Order>();
		Double amount = 0D;
		for(String id : entity.getOrderIds()) {
			Order o = orderService.get(id);
			amount = amount + o.getTotalPayAmount();
			orderList.add(o);
		}
		String bussinessNo = UuidUtil.get32UUID();
		
		WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
	    orderRequest.setBody("订单支付");
	    orderRequest.setOutTradeNo(bussinessNo);
	    orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(amount.toString()));//元转成分
	    orderRequest.setOpenid(entity.getOpenId());
	    orderRequest.setSpbillCreateIp(entity.getUserIp());
	    orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);
	    orderRequest.setNotifyUrl(entity.getNotifyUrl());
		try {
			WxPayMpOrderResult result = wxPayService.createOrder(orderRequest);
			PayOrderQuery q = new PayOrderQuery();
			for(Order o : orderList) {
				q.setBussinessNo(bussinessNo);
				q.setOrderId(o.getId());
				q.setOrderNo(o.getOrderNo());
				q.setPayType(entity.getPayType());
				this.add(q);
			}
			res.setResult(result);
			return res;
		} catch (WxPayException e) {
			logger.error("微信下单失败，{}",e.getMessage());
			res.addErrorMessage("微信下单失败");
			return res;
		}
	}
	public static Cache<String,String> cache = CacheBuilder.newBuilder()
			.maximumSize(500)
			.expireAfterWrite(60,TimeUnit.SECONDS).build();
	@Override
	public ExecuteResult<String> wxNotify(String xmlData) {
		ExecuteResult<String> res = new ExecuteResult<String>();
		res.setResult("OK");
		String wxNo = null;
		try {
			final WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
			/*WxPayOrderNotifyResult notifyResult = new WxPayOrderNotifyResult();
			notifyResult.setResultCode("SUCCESS");
			notifyResult.setReturnCode("SUCCESS");
			notifyResult.setOutTradeNo("cafd4b855c4a4bf890a5e6cee70bdf03");
			notifyResult.setTransactionId("20191009_Test2");
			notifyResult.setTotalFee(10);*/
			logger.info("微信支付回调内容：{}",notifyResult);
			if("SUCCESS".equals(notifyResult.getReturnCode()) && "SUCCESS".equals(notifyResult.getResultCode())) {
				String bussinessNo = notifyResult.getOutTradeNo();
				wxNo = notifyResult.getTransactionId();
				if(cache.getIfPresent(wxNo) != null) {
					return res;
				}
				cache.put(wxNo, StringConstant.ONE);
				PayOrderQuery payOrderQuery = new PayOrderQuery();
				payOrderQuery.setBussinessNo(bussinessNo);
				List<PayOrderQuery> list = this.listAll(payOrderQuery);
				PayOrderQuery tmp = new PayOrderQuery();
				OrderGoodsQuery ogq = new OrderGoodsQuery();
				DistributionQuery diq = new DistributionQuery();
				OrderQuery oq = new OrderQuery();
				Member mem = null;
				for(PayOrderQuery p : list) {
					tmp.getSearchMap().put(StringConstant.ID, p.getId());
					tmp.setPayOrderNo(wxNo);
					this.updatePart(tmp);
					orderService.paySuccessOrder(p.getOrderId(),"0",wxNo);
					//分销金额计算 START
					Order order = orderService.get(p.getOrderId());
					if(mem == null) {
						mem = memberService.get(order.getUserId());
						if(!"1".equals(mem.getAgentFlag())) {
							//不是代理商
							PlatformConfig pc = platformConfigService.get();
							logger.info("会员{}，支付金额：{}(分)，代理商最低金额：{}",mem.getNickName(),notifyResult.getTotalFee(),pc.getAgentAmount());
							if(pc != null && (ArithUtil.div(notifyResult.getTotalFee(),100))>=pc.getAgentAmount()) {
								//符合成为代理商条件
								logger.info("符合成为代理商条件");
								memberService.toBeAgent(mem.getId());
							}
						}
					}
					Double disAmount = 0D;
					ogq.setOrderId(p.getOrderId());
					List<OrderGoodsQuery> ogList = orderGoodsService.listAll(ogq);
					for(OrderGoodsQuery og : ogList) {
						diq.setGoodsId(og.getGoodsId());
						List<DistributionQuery> diqList = distributionService.listAll(diq);
						for(DistributionQuery dq : diqList) {
							MemberLevel ml = memberLevelService.getByMemerIdAndLevel(order.getUserId(), dq.getLevel());
							if(ml != null && "1".equals(ml.getParentAgentFlag())) {
								//增加会员冻结余额
								Double fb = ArithUtil.mul(ArithUtil.mul(og.getDealPrice(), og.getBuyNum()),dq.getRate());
								memberService.updateBalance(ml.getParentId(), 0D, fb);
								// 会员账单
								MemberBillQuery mb = new MemberBillQuery();
								mb.setType("0");
								mb.setStatus("0");
								mb.setAmount(fb);
								mb.setRemark(og.getGoodsName()+" 返利");
								mb.setUserId(ml.getParentId());
								mb.setUserName(ml.getParentName());
								mb.setBussinessId(order.getId());
								memberBillService.add(mb);
								disAmount = ArithUtil.add(disAmount, fb);
								
							}
						}
					}
					//更新订单金额   distribution_amount=disAmount  settle_amount=settle_amount-disAmount
					if(disAmount > 0) {
						oq.getSearchMap().put(StringConstant.ID, p.getOrderId());
						oq.setSettleAmount(ArithUtil.sub(order.getSettleAmount(), disAmount));
						oq.setDistributionAmount(disAmount);
						orderService.updatePart(oq);
					}
					//分销金额计算 END
				}
			}
		} catch (Exception e) {
			logger.error("微信支付回调处理失败：",e.getMessage());
			cache.invalidate(wxNo);
			res.addErrorMessage("微信支付回调处理失败");
		}

		return res;
	}
	
	
}
